<template>
  <view class="lp-multiple-select" @touchmove.stop.prevent>
    <view class="lp-multiple-select__mask"
          :style="{ 'z-index': zIndex }"
          v-show="show"
          :class="{ 'lp-multiple-select__mask-show': show }"
          @click="onCancel(true)"></view>
    <view
        class="lp-multiple-select__select-box"
        :style="{ 'z-index': zIndex, height: show ? `calc(${height + 'vh'} + 76rpx)` : 0 }"
        :class="{ 'lp-multiple-select__select-box-show': show }"
    >
      <view class="lp-multiple-select__header">
        <text class="lp-multiple-select__cancel" @click="onCancel(false)">{{cancelText}}</text>
        <text class="lp-multiple-select__title" v-if="title">{{title}}</text>
        <view class="lp-multiple-select__all" @click="onAllToggle" v-if="allShow">
          <text :class="isAll ? 'lp-multiple-select__all-active' : ''">全选</text>
        </view>
        <text class="lp-multiple-select__confirm" @click="onConfirm">{{confirmText}}</text>
      </view>
      <view
          class="lp-multiple-select__body-warp"
          :class="{ 'lp-multiple-select__safe-area-inset-bottom': safeAreaInsetBottom }"
          :style="{ height: height + 'vh' }">
        <scroll-view
            class="lp-multiple-select__body"
            scroll-y="true">
          <slot v-if="!list.length" name="empty-tips">
            <view class="lp-multiple-select__empty-tips">暂无数据~</view>
          </slot>
          <view
              class="lp-multiple-select__select-item"
              :class="[
                  item.disabled ? 'lp-multiple-select__disabled' : '',
                  item.selected ? 'lp-multiple-select__selected' : ''
                  ]"
              v-for="(item, index) in dataSource"
              :key="item[valueName]"
              @click="onSelected(item)"
          >
            <view class="lp-multiple-select__label">{{item[labelName]}}</view>
            <!--#ifndef MP-ALIPAY-->
            <text v-show="item.selected" class="lp-multiple-select__selected-icon">✔</text>
            <!--#endif-->

            <!-- #ifdef MP-ALIPAY -->
            <text v-if="item.selected" class="lp-multiple-select__selected-icon">✔</text>
            <!--#endif-->
          </view>
        </scroll-view>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  name: 'lp-multiple-select',
  model: {
    prop: "value",
    event: ["input"]
  },
  props: {
    // 双向绑定
    value: {
      type: Boolean,
      default: false,
      required: true
    },
    // 数据源
    list: {
      type: Array,
      required: true,
      default: () => []
    },
    // 取消按钮文字
    cancelText: {
      type: String,
      default: "取消"
    },
    // 确认按钮文字
    confirmText: {
      type: String,
      default: "确认"
    },
    // 顶部中间的标题
    title: {
      type: String,
      default: ""
    },
    // label对应的key名称
    labelName: {
      type: String,
      default: "label"
    },
    // value对应的key名称
    valueName: {
      type: String,
      default: "value"
    },
    // 内容区域高度：单位vh
    height: {
      type: [Number, String],
      default: 30
    },
    // 弹出时的z-index值
    zIndex: {
      type: [Number, String],
      default: 10075
    },
    // 是否允许点击遮罩层关闭
    maskCloseAble: {
      type: Boolean,
      default: true
    },
    // 是否显示全选
    allShow: {
      type: Boolean,
      default: true
    },
    // 模式
    mode: {
      type: String,
      default: "multiple",
      validator: function (value) {
        // 这个值必须匹配下列字符串中的一个
        return ['multiple'].indexOf(value) !== -1
      }
    },
    // 多选时最大选择数
    max: {
      type: Number,
      default: 99
    },
    // 默认选中值
    defaultValue: {
      type: Array,
      default: () => []
    },
    // 是否开启底部安全区适配
    safeAreaInsetBottom: {
      type: Boolean,
      default: true
    },
  },
  data() {
    return {
      show: false, //是否显示
      dataSource: [],
      selectedList: [], //选择对照列表
      selectedIds: [], //选择对照列表
      disabledCount: 0, // disabled数量
      selectedArr: [], //选择对照列表
      selectedArrOld: [] //选择对照列表上一次的数据
    };
  },
  onShow() {
    this.show = this.value;
  },
  computed: {
    // 返回是否全选
    isAll() {
      return this.selectedIds.length === (this.dataSource.length - this.disabledCount)
    }
  },
  watch: {
    async value(newVal) {
      this.show = newVal;
      this.dataSource = JSON.parse(JSON.stringify(this.list))
      this.setItemActiveState();
    },
    show(newVal) {
      this.$emit("input", newVal);
      this.$emit("change", newVal);
    },
    list() {
      this.setItemActiveState();
    },

    defaultValue: { // 监听一个对象，对应值为对象
      handler (curVal, oldVal) {
        this.defaultSelected = JSON.parse(JSON.stringify(curVal));
      },
      deep: true, // 对象内部的属性监听，深度侦听
      immediate: true // 声明的时候，就立即执行handler方法
    }
  },
  methods: {
    // 设置默认选中通用办法
    setItemActiveState() {
      if (this.dataSource.length && this.defaultSelected.length) {
        this.selectedList = []
        this.selectedIds = []
        const defaultSelected = [...this.defaultSelected]
        let disabledCount = 0 // 获取disable数量
        for(let item of this.dataSource) {
          if (!item.disabled) {
            const index = defaultSelected.findIndex(value => value.toString() === item[this.valueName].toString())
            if (index > -1) {
              item.selected = true
              this.selectedList.push(item)
              this.selectedIds.push(item[this.valueName])
            }
          } else {
            disabledCount++
          }
        }
        this.disabledCount = disabledCount
      }
    },
    /**
     * 选择事件
     * @index {Number} 点击下标
     */
    onSelected(item) {
      if (item.disabled) return;
      if (item.selected) {
        item.selected = false
        this.$forceUpdate()
        const index = this.selectedList.findIndex(row => row[this.valueName] === item[this.valueName])
        this.selectedList.splice(index, 1)
        this.selectedIds.splice(index, 1)
      } else {
        if (this.selectedIds.length >= this.max) {
          uni.showToast({
            title: `最多可选${this.max}项`,
            icon: 'none'
          });
          return;
        }
        item.selected = true
        this.$forceUpdate()
        this.selectedList.push(item)
        this.selectedIds.push(item[this.valueName])
      }
    },

    // 全选/非全选事件
    onAllToggle() {
      if(this.isAll) { // 已经全选了，所以要反选
        for(let item of this.dataSource) {
          if (!item.disabled) {
            item.selected = false
          }
        }
        this.selectedIds = []
        this.selectedList = []
      } else { // 还没全选，所以要全选
        this.selectedIds = []
        this.selectedList = []
        for(let item of this.dataSource) {
          if (!item.disabled) {
            item.selected = true
            this.selectedList.push(item)
            this.selectedIds.push(item[this.valueName])
          }
        }
      }
      this.$forceUpdate()
    },

    // 确认事件
    onConfirm() {
      this.show = false;
      this.defaultSelected = this.selectedIds
      this.$emit("confirm", this.selectedList, this.selectedIds);

      this.$nextTick(() => {
        this.dataSource = []
      })

      // if (this.mode === "multiple") {
      //   this.$emit("confirm", selectedData);
      // } else {
      //   let backData = selectedData[0] || {};
      //   this.$emit("confirm", backData);
      // }
    },

    // 取消事件
    onCancel(isMask) {
      if ((isMask && this.maskCloseAble) || !isMask) {
        this.show = false;
        this.selectedIds = JSON.parse(JSON.stringify(this.defaultSelected));
        this.$emit("cancel");
        this.$nextTick(() => {
          this.dataSource = []
        })
      }
    }
  }
};
</script>

<style>
@import '../../common/util.css';
</style>
<style lang="scss" scoped>
.lp-multiple-select {
  $paddingLR: 18rpx;

  .lp-multiple-select__mask {
    position: fixed;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    background-color: $uni-bg-color-mask;;
    transition: all 0.2s ease-in;
    opacity: 0;
    &.lp-multiple-select__mask-show {
      opacity: 1;
    }
  }
  // 选择器内容区域
  .lp-multiple-select__select-box {
    width: 100%;
    height: 0;
    position: fixed;
    bottom: 0;
    left: 0;
    //transform: translate3d(0px, 100%, 0px);
    background-color: $uni-bg-color;
    transition: height 0.2s;
    &.lp-multiple-select__select-box-show {
      //transform: translateZ(0);
    }
    .lp-multiple-select__header {
      display: flex;
      box-sizing: border-box;
      width: 100%;
      justify-content: space-between;
      border-bottom: 1px solid $uni-border-color;
      line-height: 76rpx;
      font-size: $uni-font-size-base;

      .lp-multiple-select__title {
        flex: 1 1 auto;
        margin: 0 $uni-spacing-col-base;
        max-width: calc(100vw - 320rpx);
        overflow: hidden;
        text-overflow:ellipsis;
        white-space: nowrap;
        text-align: center;
      }
      .lp-multiple-select__cancel {
        color: $uni-text-color-grey;
        padding: 0 20rpx;
      }
      .lp-multiple-select__all {
        color: $uni-color-primary;
        padding: 0 20rpx;
        .lp-multiple-select__all-active {
          &::after {
            display: inline-block;
            content: "✔";
            padding-left: 8rpx;
          }
        }
      }
      .lp-multiple-select__confirm {
        color: $uni-color-primary;
        padding: 0 20rpx;
      }
    }
    .lp-multiple-select__body-warp {
      width: 100%;
      height: 30vh;
      box-sizing: border-box;
      padding: 20rpx $paddingLR;

      .lp-multiple-select__body {
        width: 100%;
        height: 100%;
        overflow-y: auto;
        .lp-multiple-select__empty-tips {
          margin-top: 25%;
          text-align: center;
          font-size: $uni-font-size-base;
          color: $uni-color-warning;
        }
        .lp-multiple-select__select-item {
          display: flex;
          font-size: $uni-font-size-base;
          line-height: 58rpx;
          color: #303133;
          position: relative;
          &.lp-multiple-select__selected {
            color: $uni-color-primary;
          }
          &.lp-multiple-select__disabled {
            color: $uni-text-color-disable;
          }
          > .lp-multiple-select__label {
            flex: 1;
            text-align: center;
          }
          > .lp-multiple-select__selected-icon {
            position: absolute;
            right: 0;
            top: 50%;
            transform: translateY(-50%) scale(0.8);
            color: $uni-color-primary;
          }
        }
      }
    }
  }
}
</style>
